package com.j.thetabk;

import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.j.thetabk.thetas.MJpegInputStream;
import com.j.thetabk.thetas.MJpegView;
import com.j.thetabk.thetas.ThetaSBKEventListener;
import com.j.thetabk.thetas.ThetaSConnectorF;
import com.j.thetabk.thetas.ThetaSDoc;
import com.j.thetabk.thetas.ThetaSNumberA;
import com.j.thetabk.thetas.ThetaSPropertyB;

import org.json.JSONException;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;


//http://www.jianshu.com/p/e1ab1a179fbb

public class MainActivity extends AppCompatActivity {

    private ThetaSConnectorF camera = null;

    public Button[] btnC = new Button[13];
    public Button[] btnN = new Button[3];

    public TextView[] txt = new TextView[3];

    public TextView txtMsg=null;

    public Button btnLoad=null;
    public Button btnSave=null;

    public EditText fet=null;
    private RelativeLayout rl=null;


    private MJpegView mMv=null;


    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (resultCode != RESULT_OK || data == null) {
            return ;
        }

        Uri uri = data.getData();

        switch (requestCode) {
            case 2:
                fet.setText(uri.getPath());
//                Toast.makeText(this, getString(R.string.use_directory_message) + " " + uri.getPath(), Toast.LENGTH_SHORT).show();
                break;
        }
    }

    protected void ErrorExit()
    {
        Toast.makeText(this, R.string.wifi_error, Toast.LENGTH_SHORT).show();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            finishAffinity();
        }
    }


    protected String WifiSSID()
    {
        WifiManager wifiManager = (WifiManager) getSystemService(WIFI_SERVICE);
        WifiInfo wifiInfo = wifiManager.getConnectionInfo();
        Log.v("ssid",wifiInfo.getSSID());
        return wifiInfo.getSSID();
    }


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if(!WifiSSID().startsWith("\"THETAX"))
        {
            ErrorExit();
            return;
        }

        setContentView(R.layout.activity_main2);

//        this.requestWindowFeature(Window.FEATURE_NO_TITLE);

        txt[0] = (TextView) findViewById(R.id.textViewBattery);
        txt[1] = (TextView) findViewById(R.id.textViewStorage);
        txt[2] = (TextView) findViewById(R.id.textViewInfo);

        txtMsg = (TextView) findViewById(R.id.textViewMsg);
        txtMsg.setText("");

        btnC[0] = (Button) findViewById(R.id.btnwhiteBalance);
        btnC[1] = (Button) findViewById(R.id.btniso);
        btnC[2] = (Button) findViewById(R.id.btnshutterSpeed);
        btnC[3] = (Button) findViewById(R.id.btnexposureCompensation);
        btnC[4] = (Button) findViewById(R.id.btn_filter);
        btnC[5] = (Button) findViewById(R.id.btnexposureProgram);
        btnC[6] = (Button) findViewById(R.id.btncaptureMode);
        btnC[7] = (Button) findViewById(R.id.btnoffDelay);
        btnC[8] = (Button) findViewById(R.id.btnsleepDelay);
        btnC[9] = (Button) findViewById(R.id.btn_HDMIreso);
        btnC[10] = (Button) findViewById(R.id.btnfileFormat);
        btnC[11] = (Button) findViewById(R.id.btnaperture);
        btnC[12] = (Button) findViewById(R.id.btnshootDelay);

        btnN[0] = (Button) findViewById(R.id.btn_shutterVolume);
        btnN[1] = (Button) findViewById(R.id.btn_captureInterval);
        btnN[2] = (Button) findViewById(R.id.btn_captureNumber);

        btnLoad=(Button)findViewById(R.id.btnLoad);
        btnSave=(Button)findViewById(R.id.btnSave);

        fet=(EditText)findViewById(R.id.editText);
        rl=(RelativeLayout)findViewById(R.id.bk);

        mMv = (MJpegView) findViewById(R.id.live_view);

        camera = new ThetaSConnectorF("192.168.1.1");



        camera.doc.LoadDir(getPreferences(Context.MODE_PRIVATE));

        fet.setText(camera.doc.sDir);

        fet.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {

                Intent intent = new Intent("com.estrongs.action.PICK_DIRECTORY");
                intent.putExtra("com.estrongs.intent.extra.TITLE", "Select Directory");
                // Assign a path.
                intent.setData(Uri.parse("file://" + fet.getText()));

                try {
                    startActivityForResult(intent, 2);
                } catch (ActivityNotFoundException e) {
                    // No compatible file manager was found.
//                    Toast.makeText(this, getString(R.string.no_filemanager_installed), Toast.LENGTH_SHORT).show();
                }

            }
        });


        fet.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {

            }

            @Override
            public void afterTextChanged(Editable s) {
                camera.doc.sDir = s.toString();
                camera.doc.SaveDir(getPreferences(Context.MODE_PRIVATE));
            }
        });


        new ConnectTask().execute();

    }

    private void DisplayChoice(int index)
    {
        String str= camera.properties[index].DisplayChoice(index);
        if(str==null) {
            btnC[index].setVisibility(View.GONE);
            return;
        }
        btnC[index].setVisibility(View.VISIBLE);
        btnC[index].setText(str);
    }
    private void DisplayNumber(int index)
    {
        String str= camera.numbers[index].DisplayNumber(index);
        if(str==null) {
            btnN[index].setVisibility(View.GONE);
            return;
        }
        btnN[index].setVisibility(View.VISIBLE);
        btnN[index].setText(str);
    }

    private void DisplayBattery()
    {
        txt[0].setTextColor(camera.BatteryState());
        txt[0].setText(camera.BatteryStr());
    }

    private void DisplayStorage()
    {
        txt[1].setText(camera.StorageStr());
    }

    private void DisplayInfo(String msg)
    {
        txt[2].setText(camera.InfoStr()+"\n\n"+msg);
    }

    private void SetClickable(boolean flg) {
        for (Button btn:btnC)
            btn.setClickable(flg);
        for (Button btn:btnN)
            btn.setClickable(flg);
        fet.setClickable(flg);
        rl.setClickable(flg);
        btnLoad.setClickable(flg);
        btnSave.setClickable(flg);
    }

    private class ConnectTask extends AsyncTask<Void, String, Boolean> {
        @Override
        protected void onPreExecute() {

            SetClickable(false);

            super.onPreExecute();
        }

        @Override
        protected void onPostExecute(Boolean aVoid) {

            super.onPostExecute(aVoid);

            if(!aVoid)
            {
                ErrorExit();
                return;
            }

            for(int i=0;i<13;i++)
            {
                DisplayChoice(i);
            }

            for(int i=0;i<3;i++)
            {
                DisplayNumber(i);
            }

            DisplayBattery();
            DisplayStorage();
            DisplayInfo("");

            for(int i=0;i<camera.properties.length;i++)
            {
                camera.properties[i].mListener=new ThetaSPropertyChangeListener(i);
                btnC[i].setOnClickListener(new ChoiceOnClickListener(i));
            }

            for(int i=0;i<camera.numbers.length;i++)
            {
                camera.numbers[i].mListener=new ThetaSNumberChangeListener(i);
                btnN[i].setOnClickListener(new ValueOnClickListener(i));
            }

            camera.doc.mListener=new FileListener();

            btnLoad.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    camera.doc.LoadSettingList(MainActivity.this);
                }
            });
            btnSave.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    camera.doc.EditSettingName(MainActivity.this);
                }
            });

            rl.setOnClickListener(new ButtonPreviewOnClickListener());

            SetClickable(true);

            if(camera.Mode()==1)
            {
                goTask=true;
                clicked=false;
                new UpdateTask(0).execute();
                SetClickable(camera.IsIdle());
                txt[2].setVisibility(View.VISIBLE);
            }
            else
            {
                if(camera.IsIdle())
                {
                    new LiveTask().execute();
                    SetClickable(true);
                }
                else
                {
                    SetClickable(false);
                    txt[2].setVisibility(View.VISIBLE);
                }
            }

        }

        @Override
        protected Boolean doInBackground(Void... params) {
            try {
                camera.Sync();
            } catch (Throwable throwable) {
                return false;
            }
            return true;
        }
    }

    public class ChoiceOnClickListener implements View.OnClickListener {

        public int pIndex = 0;

        public ChoiceOnClickListener(int pind) {
            pIndex = pind;
        }

        @Override
        public void onClick(View v) {
            if(pIndex==5 && camera.properties[4].choice!=0)
                return;
            camera.properties[pIndex].PopList(MainActivity.this,pIndex);
        }
    }

    public class ValueOnClickListener implements View.OnClickListener {

        public int pIndex = 0;

        public ValueOnClickListener(int pind) {
            pIndex = pind;
        }

        @Override
        public void onClick(View v) {
            camera.numbers[pIndex].PopList(MainActivity.this,pIndex);
        }
    }

    public class ThetaSPropertyChangeListener implements ThetaSPropertyB.PropertyChangeListener
    {
        private int index=0;

        public ThetaSPropertyChangeListener(int idx)
        {
            index=idx;
        }


        private class SetPropertyTask extends AsyncTask<Integer, String, int[]> {

            @Override
            protected int[] doInBackground(Integer... params) {
                try {
                    return camera.SetProperty(params[0]);
                } catch (Throwable throwable) {
                    return null;
                }
            }

            @Override
            protected void onPostExecute(int[] ints) {
                super.onPostExecute(ints);
                if(ints!=null)
                {
                    for (int aSyncIndex : ints)
                    {
                        if(aSyncIndex==-1)
                            DisplayStorage();
                        else
                            DisplayChoice(aSyncIndex);
                    }
                }

                if(index==6)
                {
                    if(camera.Mode()==1)
                    {
                        mMv.stopPlay();
                        txt[2].setVisibility(View.VISIBLE);

                        goTask=true;
                        clicked=false;
                        new UpdateTask(0).execute();
                        SetClickable(camera.IsIdle());


                    }
                    else
                    {
                        goTask=false;

                        new LiveTask().execute();
                        SetClickable(true);

                    }
                }


            }
        }


        @Override
        public void onChoiceChanged() {
            new SetPropertyTask().execute(index);
        }

        @Override
        public void onCheckNumChanged() {
            DisplayChoice(index);
        }
    }

    public class ThetaSNumberChangeListener implements ThetaSNumberA.NumberChangeListener
    {
        private int index=0;

        public ThetaSNumberChangeListener(int idx)
        {
            index=idx;
        }

        private class SetNumberTask extends AsyncTask<Integer, String, Boolean> {
            @Override
            protected void onPostExecute(Boolean aBoolean) {
                super.onPostExecute(aBoolean);
                if(aBoolean)
                    DisplayNumber(index);
            }

            @Override
            protected Boolean doInBackground(Integer... params) {
                try {
                    return camera.SetNumber(params[0]);
                } catch (Throwable throwable) {
                    return false;
                }
            }
        }

        @Override
        public void onValueChanged() {
            new SetNumberTask().execute(index);
        }
    }

    public class FileListener implements ThetaSDoc.PropertyChangeListener
    {

        @Override
        public void onNameChanged() {
            try {
                camera.SaveSettingSD();
                txtMsg.setText("setting save as " + camera.doc.settingName + camera.doc.settingExtension);
            } catch (IOException e) {
                e.printStackTrace();
                txtMsg.setText("fail saving setting");
            }
        }

        @Override
        public void onFolderChanged() {

        }

        @Override
        public void onFileListEmpty() {
            txtMsg.setText("no setting file");
        }

        @Override
        public void onSelectFile(File file) {
            new LoadSettingTask(file).execute();
        }


        private class LoadSettingTask extends AsyncTask<File, String, Boolean> {

            private File file=null;

            public LoadSettingTask(File f)
            {
                file=f;
            }

            @Override
            protected void onPostExecute(Boolean aDouble) {
                super.onPostExecute(aDouble);
                if(aDouble) {
                    txtMsg.setText("load setting file " + file.getName());
                    for (int i = 0; i < 6; i++)
                        DisplayChoice(i);
                }
            }

            @Override
            protected Boolean doInBackground(File... params) {
                try {
                    return camera.LoadSettingSD(file.getAbsolutePath());
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (JSONException e) {
                    e.printStackTrace();
                }
                return false;
            }
        }

    }

    private class CaptureListener implements ThetaSBKEventListener {

        @Override
        public void onObjectChanged(final int stackIndex, final int bracketIndex)
        {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    DisplayBattery();
                    DisplayStorage();
                    DisplayInfo(camera.ProgressMsg(stackIndex, bracketIndex));
                }
            });
        }

        @Override
        public void onPropertyChanged(final int pIndex) {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    DisplayChoice(pIndex);
                }
            });
        }

        @Override
        public void onError(final String errorMessage) {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    DisplayInfo(errorMessage);
                }
            });
        }

        @Override
        public void onComplete() {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    DisplayInfo("complete");
                }
            });
        }

        @Override
        public void onSaveImageList(final String fileName) {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    txtMsg.setText("file list save as " + fileName);
                }
            });
        }

        @Override
        public void onCountDown(final int sec) {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    if(sec>0)
                        DisplayInfo("counting down " + sec);
                    else
                        DisplayInfo("starting...");
                }
            });
        }
    }

    private class ShootTask extends AsyncTask<Void, String, Void> {

        private boolean restartLive=false;

        @Override
        protected void onPreExecute() {
            super.onPreExecute();

            restartLive=false;
            if(txt[2]!=null && txt[2].getVisibility()==View.INVISIBLE)
            {
                mMv.stopPlay();
                txt[2].setVisibility(View.VISIBLE);
                restartLive=true;
            }

            SetClickable(false);
            txtMsg.setText("");
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);

            if(restartLive) {
                new LiveTask().execute();
            }

            SetClickable(true);
        }

        @Override
        protected Void doInBackground(Void... params) {

            try {
                camera.TakePhotoBK(new CaptureListener(),200);
            } catch (IOException e) {
                e.printStackTrace();
            } catch (JSONException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return null;
        }
    }

    private class LiveTask extends AsyncTask<Void, Void, MJpegInputStream> {

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            mMv.play();
        }

        @Override
        protected MJpegInputStream doInBackground(Void... params) {
            for (int retryCount = 0; retryCount < 20; retryCount++) {
                try {
                    InputStream is = camera.GetLivePreview();
                    return new MJpegInputStream(is);
                } catch (IOException | JSONException e) {
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e1) {
                        e1.printStackTrace();
                    }
                }
            }
            return null;
        }

        @Override
        protected void onPostExecute(MJpegInputStream mJpegInputStream) {
            if (mJpegInputStream != null) {
                mMv.setSource(mJpegInputStream);
                txt[2].setVisibility(View.INVISIBLE);
            }
            else
            {
                txt[2].setVisibility(View.VISIBLE);
            }
        }

    }

    public class ButtonPreviewOnClickListener implements View.OnClickListener
    {

        @Override
        public void onClick(View v) {

            if(camera.Mode()!=0)
                return;

            Log.v("ButtonPreview","click");

            if(txt[2].getVisibility()==View.VISIBLE)
            {
                new LiveTask().execute();
            }
            else
            {
                mMv.stopPlay();
                txt[2].setVisibility(View.VISIBLE);
            }
        }
    }

    public boolean goTask;
    public boolean clicked;

    public class UpdateTask extends AsyncTask<Void, String, Integer> {

        private long segCount;

        public UpdateTask(long sc)
        {
            segCount=sc;
        }

        @Override
        protected Integer doInBackground(Void... params) {

//                long startTime = System.nanoTime();

            try {
                return camera.VideoRecordUpdate(clicked,700);
            } catch (IOException | JSONException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
//                long endTime = System.nanoTime();
//                System.out.println("程序运行时间： " + (endTime - startTime) / 1000000 + "ms");

            Log.v("UpdateTask","error");

            return -1;
        }

        @Override
        protected void onPostExecute(final Integer integer) {

            Log.v("UpdateTask","onPostExecute"+integer);
            switch (integer)
            {
                case 0:
                    if(goTask)
                    {
                        new UpdateTask(segCount).execute();
                        DisplayInfo(camera.RecordingMsg(segCount));
                    }
                    SetClickable(false);
                    break;
                case 1:
                    clicked=false;
                    if(goTask)
                    {
                        new UpdateTask(segCount).execute();
                        DisplayInfo(camera.RecordingMsg(segCount));
                    }
                    SetClickable(false);
                    break;
                case 2:
                    clicked=false;
                    if(goTask)
                    {
                        new UpdateTask(segCount).execute();
                        DisplayInfo(camera.RecordingMsg(segCount));
                    }
                    break;
                case 3:
                    if(goTask)
                    {
                        new UpdateTask(segCount+1).execute();
                        DisplayInfo(camera.RecordingMsg(segCount));
                    }
                    DisplayStorage();
                    break;
                case 4:
                    if(goTask)
                    {
                        new UpdateTask(0).execute();
                    }
                    DisplayInfo("");
                    DisplayStorage();
                    SetClickable(true);
                    break;
                default:
                    break;
            }
            DisplayBattery();

        }

    }

    @Override
    protected void onResume() {
        super.onResume();

            if(camera!=null && camera.Mode()==0)
            {
                if(txt[2]!=null && txt[2].getVisibility()==View.INVISIBLE)
                {
                   new LiveTask().execute();
                    Log.v("onResume", "visible");
                }
            }

        Log.v("onResume","onResume");

    }

    @Override
    protected void onPause() {
        super.onPause();


            if(camera!=null && camera.Mode()==0)
            {
                if(txt[2]!=null && txt[2].getVisibility()==View.INVISIBLE)
                {
                    mMv.stopPlay();
//                    txt[2].setVisibility(View.VISIBLE);
                    Log.v("onPause", "visible");
                }
            }

        Log.v("onPause", "invisible");

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        goTask=false;
        if(mMv!=null)
            mMv.stopPlay();

        Log.v("onDestroy", "onDestroy");
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {

        switch (keyCode)
        {
            case KeyEvent.KEYCODE_VOLUME_DOWN:
            case KeyEvent.KEYCODE_VOLUME_UP:
                if(camera.Mode()==0) {
                    if (btnC[0].isClickable()) {
                        new ShootTask().execute();
                    }
                }
                else
                {
                    clicked=true;
                }
                return true;
        }


        return super.onKeyDown(keyCode, event);
    }
}
